/**
 * 题四:
 * 手写实现 MyPromise 源码
 * 尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述原理
 */

const MyPromise = require('./q4/MyPromise');

/**
 * 1. 基础功能
 *    提供一个类, 可接受一个函数(functor执行器),
 *    在该函数中可获取 resolve 及 reject 函数引用
 *    resolve 负责变更对象状态至 fulfilled 并可接受一个值(value), 最为值储存
 *    reject 负责变更对象状态至 rejected 并可接受一个值(reason), 作为失败原因储存
 *    状态仅变更一次.
 *    通过该类创建的对象, 提供 then 函数, 该函数接受两个参数 success, fail
 *    当 then 执行时且状态为 fulfilled, 就调用 success, 并将 value 传入,
 *    如状态为 rejected, 就调用 fail, 并将 reason 传入
 */
const p1 = new MyPromise((resolve, reject) => {
  resolve('成功');
  reject('失败');
});
console.info('1. 基础功能');
p1.then(
  (v) => console.info('成功:', v),
  (e) => console.info('失败:', e)
);

/**
 * 2. 加入异步逻辑, 即支持异步变更状态
 */

const p2 = new MyPromise((resolve) => {
  setTimeout(() => resolve('延迟一秒'), 1000);
});

p2.then((v) => {
  console.info('2. 支持异步变更状态');
  console.info('成功:', v);
});

/**
 * 3. then 支持多次调用
 */
const p3 = new MyPromise((resolve) => setTimeout(() => resolve('多次')), 0);

p3.then((v) => {
  console.info('3. then 支持多次调用');
  console.info('成功:', v);
});

p3.then((v) => {
  console.info('3. then 支持多次调用2');
  console.info('成功:', v);
});

/**
 * 4. then 支持链式调用, 并可接受上一个调用的返回值
 */

const p4 = new MyPromise((resolve) => {
  resolve('同步链式调用');
});

p4.then(
  (v) => {
    console.info('4. 支持链式调用');
    console.info('成功:', v);
    return '成功2';
  },
  (e) => console.info('失败:', e)
).then((v) => {
  console.info('4. 支持链式调用2');
  console.info('成功:', v);
});

/**
 * 5. then 支持链式调用, 并可接受上一个调用的返回值, 且返回值为 MyPromise 对象
 */

const p5 = new MyPromise((resolve) => {
  resolve('同步链式调用2');
});

p5.then((v) => {
  console.info('5. 链式调用2, 识别 Promise 对象返回');
  console.info('成功:', v);
  return new MyPromise((r) => r('返回Promise对象的值'));
}).then((v) => console.info('成功:', v));

/**
 * 6. then 链式调用识别自返回
 */

let p6 = new MyPromise((r) => {
  r('自返回');
});

p6 = p6
  .then(() => {
    console.info('6. 自返回识别', p6);
    return p6;
  })
  .then(null, (e) => console.info('exxxxxxxxxx', e));

/**
 * 7. 捕获错误, 支持失败流程, 及异步注册
 */

const p7 = new MyPromise((resolve, reject) => {
  // throw new Error('执行器失败');
  setTimeout(() => resolve('p7'), 1500);
});

p7.then(
  (v) => {
    console.info('7. 捕获错误, 支持失败流程, 及异步注册');
    console.info('成功:', v);
    // throw new Error('then 失败');
  },
  (e) => {
    console.error('失败:', e.message);
  }
);

new MyPromise((a, b) => b('x')).then().then(
  (c) => console.info('11111111', c),
  (e) => console.info('22222222', e)
);

MyPromise.resolve(1).then((v) => console.info('resolve', v));
MyPromise.reject(2).then(null, (e) => console.error('reject', e));
